(function() {
  var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };

  define(['chaplin', 'lib/dao_factory', 'lib/enums', 'lib/ajax_setup'], function(Chaplin, DaoFactory, Enums, ajaxSetup) {
    'use strict';
    var Dao;
    return Dao = (function() {
      Dao.prototype.baseUrl = '/';

      Dao.prototype.modelClass = null;

      Dao.prototype.collectionClass = null;

      function Dao(baseUrl) {
        if (baseUrl == null) {
          baseUrl = '/';
        }
        this.defaultPromiseError = __bind(this.defaultPromiseError, this);
        this.setBaseUrl(baseUrl);
      }

      Dao.prototype.setBaseUrl = function(baseUrl) {
        this.baseUrl = baseUrl;
        if (this.baseUrl.charAt(this.baseUrl.length - 1) !== "/") {
          return this.baseUrl = this.baseUrl + "/";
        }
      };

      Dao.prototype.removeWhitespaces = function(data) {
        var key, value, _results;
        if (_.isObject(data)) {
          _results = [];
          for (key in data) {
            value = data[key];
            if (_.isString(value)) {
              _results.push(data[key] = value.replace(/\s\s+/g, ' '));
            } else {
              _results.push(void 0);
            }
          }
          return _results;
        }
      };

      Dao.prototype.fetchCollection = function(type, url, params, data) {
        var ajaxPromise, promise,
          _this = this;
        if (type == null) {
          type = "GET";
        }
        if (url == null) {
          url = "";
        }
        if (params == null) {
          params = [];
        }
        if (data == null) {
          data = {};
        }
        promise = $.Deferred();
        this.removeWhitespaces(data);
        ajaxPromise = $.ajax({
          url: this.constructUrl(url, params),
          type: type,
          dataType: 'json',
          data: data
        });
        ajaxPromise.fail(this.defaultPromiseError(promise)).done(function(json, status, ajaxObj) {
          var collection;
          collection = new _this.collectionClass(json);
          return promise.resolve.apply(_this, [collection, ajaxObj]);
        });
        return promise;
      };

      Dao.prototype.defaultPromiseError = function(promise) {
        var func,
          _this = this;
        return func = function(error) {
          ajaxSetup.error.apply(_this, arguments);
          return promise.reject.apply(_this, arguments);
        };
      };

      Dao.prototype.fetchModel = function(type, url, params, data) {
        var ajaxPromise, promise,
          _this = this;
        if (type == null) {
          type = "GET";
        }
        if (url == null) {
          url = "";
        }
        if (params == null) {
          params = [];
        }
        if (data == null) {
          data = {};
        }
        if (_.isObject(url)) {
          data = url;
          url = "";
        }
        this.removeWhitespaces(data);
        promise = $.Deferred();
        ajaxPromise = $.ajax({
          url: this.constructUrl(url, params),
          type: type,
          dataType: 'json',
          data: data
        });
        ajaxPromise.fail(this.defaultPromiseError(promise)).done(function(json, status, ajaxObj) {
          var model;
          model = new _this.modelClass(json);
          return promise.resolve.apply(_this, [model, ajaxObj]);
        });
        return promise;
      };

      Dao.prototype.fetchRaw = function(type, url, params, data, options) {
        var ajaxOptions, ajaxPromise, oldType, promise,
          _this = this;
        if (type == null) {
          type = "GET";
        }
        if (url == null) {
          url = "";
        }
        if (params == null) {
          params = [];
        }
        if (data == null) {
          data = {};
        }
        if (options == null) {
          options = {};
        }
        if (_.isObject(url)) {
          data = url;
          url = "";
        }
        this.removeWhitespaces(data);
        if (_.indexOf(['PUT', 'DELETE'], type) >= 0 && options.contentType !== 'application/json; charset=UTF-8') {
          oldType = type;
          type = 'POST';
          data['_method'] = oldType;
        }
        promise = $.Deferred();
        ajaxOptions = {
          url: this.constructUrl(url, params),
          type: type,
          dataType: 'json',
          data: data
        };
        ajaxOptions = _.extend(ajaxOptions, options);
        if (ajaxOptions.contentType === 'application/json; charset=UTF-8') {
          ajaxOptions.data = window.JSON.stringify(ajaxOptions.data);
        }
        ajaxPromise = $.ajax(ajaxOptions);
        ajaxPromise.fail(this.defaultPromiseError(promise)).done(function(json, status, ajaxObj) {
          return promise.resolve.apply(_this, [json, ajaxObj]);
        });
        return promise;
      };

      Dao.prototype.listar = function() {
        return this.fetchCollection("GET");
      };

      Dao.prototype.remover = function(id) {
        return this.fetchModel("DELETE", "{0}", [id]);
      };

      Dao.prototype.atualizar = function(id, data) {
        return this.fetchModel("PUT", "{0}", [id], data);
      };

      Dao.prototype.criar = function(data) {
        return this.fetchModel("POST", "{0}", null, data);
      };

      Dao.prototype.ler = function(id) {
        return this.fetchModel("GET", "{0}", [id]);
      };

      Dao.prototype.constructUrl = function(url, params) {
        var param, paramIndex, replaceParam, _i, _len;
        replaceParam = function(param, index) {
          var reg;
          reg = new RegExp("\\{" + index + "\\}");
          return url = url.replace(reg, param);
        };
        for (paramIndex = _i = 0, _len = params.length; _i < _len; paramIndex = ++_i) {
          param = params[paramIndex];
          replaceParam(param, paramIndex);
        }
        if (url.indexOf('http://') < 0) {
          url = this.baseUrl + url;
        }
        return url;
      };

      return Dao;

    })();
  });

}).call(this);
